package cn.easyutil.veteran.web.handler;

import cn.easyutil.veteran.core.utils.SpringUtils;
import cn.easyutil.veteran.web.advice.JsonRequestAdvice;
import cn.easyutil.veteran.web.provider.DefaultJsonRequestAdvice;
import cn.easyutil.veteran.web.session.SessionOperation;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;

/**
 * 请求体为raw类型时进入本拦截器
 */
@Component
public class JsonRequestHandle extends MappingJackson2HttpMessageConverter {

    private final ObjectMapper objectMapper;

    private JsonRequestAdvice jsonRequestAdvice;
    private final JsonRequestAdvice defaultAdvice = new DefaultJsonRequestAdvice();

    public JsonRequestHandle(ObjectMapper objectMapper) {
        super(objectMapper);
        this.objectMapper = objectMapper;
    }

    /**
     * type:请求controller中的参数类型
     * contextClass:请求的controller类
     * inputMessage:请求的body体
     */
    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException {

        //读取用户的请求数据
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        int i;
        while ((i = inputMessage.getBody().read()) != -1) {
            stream.write(i);
        }
        JavaType javaType = getJavaType(type, contextClass);
        //读取到原始请求数据
        String text = stream.toString();
        //处理请求数据
        text = getAdvice().parseBody(text,javaType,type,contextClass);
        //包装接口对应的实体对象
        Object body = this.objectMapper.readerFor(javaType).readValue(text);
        SessionOperation.requestParams.set(body);
        return getAdvice().beforeInvocation(body);
    }

    @Override
    protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {

        super.writeInternal(object, type, outputMessage);
    }

    public JsonRequestAdvice getAdvice(){
        if(this.jsonRequestAdvice != null){
            return this.jsonRequestAdvice;
        }
        JsonRequestAdvice jsonRequestAdvice = SpringUtils.getBean(JsonRequestAdvice.class);
        if(jsonRequestAdvice == null){
            return defaultAdvice;
        }
        this.jsonRequestAdvice = jsonRequestAdvice;
        return this.jsonRequestAdvice;
    }
}
